package com.cpit.platform.datasource;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

@Aspect
@Order(-10)//保证该AOP在@Transactional之前执行
@Component
public class DataSourceAspect {
    /*
     * @Before("@annotation(ds)") 的意思是：
     * @Before：在方法执行之前进行执行：
     * @annotation(targetDataSource)：
     * 会拦截注解targetDataSource的方法，否则不拦截;
     */
    @Before("@annotation(targetDataSource)")
    public void changeDataSource(JoinPoint joinPoint, TargetDataSource targetDataSource) throws Throwable {
        Class clazz = joinPoint.getTarget().getClass();
        System.out.println(" joinPoint.getTarget().getClass() = "+ joinPoint.getTarget().getClass().getSimpleName());
        System.out.println("  joinPoint.getSignature().getClass() = "+  joinPoint.getSignature().getClass().getSimpleName());
        System.out.println("  joinPoint.getSignature().getName() = "+  joinPoint.getSignature().getName());
        System.out.println("  joinPoint.getSignature().getDeclaringTypeName() = "+  joinPoint.getSignature().getDeclaringTypeName());
        String newTargetDataSourceId = targetDataSource.value();
        Signature signature = joinPoint.getSignature();
        if (signature instanceof MethodSignature){
            Method method = ((MethodSignature) signature).getMethod();
            TargetDataSource newTargetDataSource = method.getAnnotation(TargetDataSource.class);
            if (TargetDataSource.TYPE_ARGUMENT.equalsIgnoreCase(newTargetDataSource.type())){
                Class[] parameterTypes = ((MethodSignature)joinPoint.getSignature()).getMethod().getParameterTypes();
                if(parameterTypes[newTargetDataSource.position()] == String.class){
                }else{
                }
                newTargetDataSourceId = (String) joinPoint.getArgs()[newTargetDataSource.position()];
            }else{
                newTargetDataSourceId = (newTargetDataSource == null? null:newTargetDataSource.value());
            }
        }
        //如果不在我们注入的所有的数据源范围之内，那么输出警告信息，系统自动使用默认的数据源。
        if (newTargetDataSourceId == null || !DataSourceContextHolder.containsDataSource(newTargetDataSourceId)) {
            System.err.println("数据源[{}]不存在，使用默认数据源 > {}"+ (newTargetDataSourceId == null? "":newTargetDataSourceId) +" In "+joinPoint.getSignature());
        } else {
            System.out.println("Use DataSource : {} > {}"+newTargetDataSourceId+joinPoint.getSignature());
            DataSourceContextHolder.setDataSource(newTargetDataSourceId);
        }
    }

    @After("@annotation(targetDataSource)")
    public void restoreDataSource(JoinPoint point, TargetDataSource targetDataSource) {
        System.out.println("Revert DataSource : {} > {}"+targetDataSource.value()+point.getSignature());
        //方法执行完毕之后，销毁当前数据源信息，进行垃圾回收。
        DataSourceContextHolder.clearDataSource();
    }
}